package com.wutong.engine.entity;

import com.almasb.fxgl.dsl.EntityBuilder;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.physics.HitBox;
import com.wutong.engine.anything.GameLogger;
import com.wutong.engine.entity.animation.Animation;
import com.wutong.engine.entity.enums.Direction;
import com.wutong.engine.entity.interfaces.OnAddedFunction;
import javafx.scene.Node;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Optional;

/**
 * 游戏实体在引擎的二次封装
 *
 * @author 王益凡
 */
public class GameEntity {
    private static final Logger log = GameLogger.getLogger(GameEntity.class);

    private static int entityId = 100000;
    private String entityName;

    private final int id;

    private final EntityBuilder builder = FXGL.entityBuilder();
    private Entity thisEntity;

    private Animation animation;
    private final double[] pointAt = {0.0, 0.0};

    private final ArrayList<Component> components = new ArrayList<>();
    private Node node;
    private HitBox hitBox;
    private String assetsTexture;

    private Direction direction;

    public GameEntity(String entityName) {
        this.id = entityId++;
        this.entityName = entityName;
        log.info("创建实体，Id: {}, 实体名: {}", id, entityName);
    }

    public void createEntity() {
        log.info("生成实体");
        builder.at(pointAt[0], pointAt[1]);
        if (!components.isEmpty()) {
            log.info("载入组件...");
            for (Component component : components) {
                builder.with(component);
            }
            log.info("成功载入 {} 个组件", components.size());
        }
        if (Optional.ofNullable(animation).isPresent()) {
            log.info("载入动画...");
            builder.with(animation);
            log.info("动画载入完毕");
        }
        if (Optional.ofNullable(hitBox).isPresent()) {
            builder.bbox(hitBox);
        }
        if (Optional.ofNullable(node).isPresent() && Optional.ofNullable(assetsTexture).isEmpty()) {
            log.info("载入视图");
            builder.view(node);
            log.info("视图载入完毕");
        } else if (Optional.ofNullable(assetsTexture).isPresent() && Optional.ofNullable(node).isPresent()) {
            log.info("载入材质");
            builder.view(assetsTexture);
            log.info("材质载入完毕");
        } else if (Optional.ofNullable(assetsTexture).isPresent()) {
            log.error("视图与材质不能被同时载入，默认选择载入视图");
            builder.view(node);
            log.info("选取视图载入完毕");
        }
        log.info("构建实体...");
        thisEntity = builder.buildAndAttach();
        log.info("完成实体构建，当前实体为 -> {}: {}", id, entityName);
    }

    public GameEntity setPosition(double x, double y) {
        pointAt[0] = x;
        pointAt[1] = y;
        return this;
    }

    public void move(double d, Direction direction, OnAddedFunction onAddedFunction) {
        switch (direction) {
            case Up -> thisEntity.translateY(-d);
            case Down -> thisEntity.translateY(d);
            case Left -> thisEntity.translateX(-d);
            case Right -> thisEntity.translateX(d);
        }
        onAddedFunction.onAdded();
    }

    public void move(double d, Direction direction) {
        this.move(d, direction, () -> {
        });
    }

    public void moveByAnimation(Direction direction) {
        this.direction = direction;
    }

    public GameEntity addComponent(Component component) {
        log.warn("该方法可能导致未知的错误！");
        this.components.add(component);
        return this;
    }

    public GameEntity addView(Node nodeView) {
        node = nodeView;
        return this;
    }

    public GameEntity addView(String viewImagePath) {
        assetsTexture = viewImagePath;
        return this;
    }

    public GameEntity addAnimation(Animation animation) {
        this.animation = animation;
        return this;
    }

    public GameEntity addHitBox(HitBox hitBox) {
        this.hitBox = hitBox;
        return this;
    }

    public Animation getAnimation() {
        return animation;
    }

    public Entity getEntity() {
        return thisEntity;
    }

    public int getId() {
        return id;
    }

    public String getEntityName() {
        return entityName;
    }

    public EntityBuilder getBuilder() {
        return builder;
    }

    public void setEntityName(String entityName) {
        this.entityName = entityName;
    }
}
